package cu.tedu._05weibo.excepetion;

import cu.tedu._05weibo.common.response.JsonResult;
import cu.tedu._05weibo.common.response.StatusCode;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice;

import javax.validation.ConstraintViolationException;

/**
 * Spring MVC 全局异常处理器;
 * RestControllerAdvice注解:组合注解, 相当于ContrllerAdvice + Response 注解组合;
 *   1.标识此类为Spring MVC全局异常处理器的类;
 *   2.一旦控制器抛出异常,框架会检查是否定义了全局异常处理器;
 *     2.1 如果未定义,则使用框架内置的异常处理机制[不友好];
 *     2.2 如果定义了,则会在此类中定位异常处理方法;
 */
@Slf4j
@RestControllerAdvice
public class GlobalExceptionHandler {

    /**
     * 第1个异常处理方法：参数异常
     * 定义异常处理方法
     * ExceptionHandler注解：
     *   1.标识此方法为异常处理方法;
     */
    @ExceptionHandler
    public JsonResult doHandle(IllegalArgumentException exception) {
        String message = exception.getMessage();
        log.error("doHandle:" + message);
        return new JsonResult(StatusCode.OPERATION_FAILED, message);
    }

    /**
     * 第4个异常处理方法：运行异常[父类]
     * 当控制器抛出异常后：
     * 1.是否定义了全局异常处理器;
     * 2.定义了,则该异常对应的异常处理方法;
     * 3.如果未找到,则继续找该异常的父类异常的异常处理方法;
     * 4.如果父类也未找到,则找能够处理所有异常的Throwable处理方法;
     * 5.如果未定义此方法,则走Spring MVC内置的异常处理机制[不友好].
     */

    @ExceptionHandler
    public JsonResult Runtime(RuntimeException e) {
        log.error("Runtime:" + e.getMessage());
        return new JsonResult(StatusCode.OPERATION_FAILED, e);
    }

//    @ExceptionHandler
//    public JsonResult Throwable(Throwable e) {
//        log.error("Throwable:" + e.getMessage());
//        return new JsonResult(StatusCode.OPERATION_FAILED, e);
//    }


    /**
     * 第3个异常处理方法：验证DTO类方式接收数据异常
     */

    @ExceptionHandler
    public JsonResult MethodArgumentNotValidException(MethodArgumentNotValidException exception) {
        /*

         */
        String message= exception.getFieldError().getDefaultMessage();
        log.error("MethodArgumentNotValidException:"+message);
        return new JsonResult(StatusCode.VALIDATED_ERROR,message);
    }

    /**
     * 第3个异常处理方法:声明参数方式接收的异常处理方法
     */
    @ExceptionHandler
    public JsonResult ConstraintViolationException(ConstraintViolationException exception){
        String message= exception.getMessage().split(":")[1].trim();
        log.error("ConstraintViolationException:"+message);
        return new JsonResult(StatusCode.VALIDATED_ERROR,message);
    }

}
